即使是这些简单的函数模板示例，也可能引发进一步的问题。有三个常见问题，在这里简单的讨论下。

\subsubsubsection{1.6.1\hspace{0.2cm}使用值，还是引用传递参数?}

为什么通常声明函数按值传递参数，而不是使用引用。一般来说，除了简单类型(比如基本类型或\texttt{std::string\_view})，因为不会创建副本，所以推荐使用引用传递。

然而，按值传递在下面的情况下会更好:

\begin{itemize}
\item
语法简单。

\item 
编译器会进行很好的优化。

\item
移动语义会使复制成本降低。

\item 
没有复制或移动操作。
\end{itemize}

此外，对于模板来说:

\begin{itemize}
\item
模板可能同时用于简单类型和复杂类型，因此为复杂类型选择这种方法时，可能会对简单类型产生反效果。

\item 
作为调用者，可以通过引用来传递参数，可以使用\texttt{std::ref()}和\texttt{std::cref()}(参见7.3节)。

\item
虽然传递字符串字面值或原始数组可能会产生问题，但通过引用传递通常会有更多的问题。
\end{itemize}

这些将在第7章中详细讨论。目前，我们使用值传递参数(除非某些功能只有在使用引用时才使用引用)。

\subsubsubsection{1.6.2\hspace{0.2cm}为什么不用内联?}
 
通常，函数模板不必使用内联声明。与普通的非内联函数不同，我们可以在头文件中定义非内联函数模板，并在多个翻译单元中包含该头文件。

该规则的唯一例外是，对特定类型的模板进行完全特化，从而产生的代码不再是泛型(定义了所有模板参数)。参见9.2节了解更多细节。
 
从严格的语言定义角度来看，内联意味着函数的定义可以在程序中出现多次。也表示编译器对该函数的调用应该“内联展开”:某些情况下可以产生更有效的代码，但在许多其他情况下反而会降低代码的效率。现在，编译器通常能够更好地决定是否采纳使用inline关键字的提示。但是，编译器仍然要考虑在该决策中是否存在内联。

\subsubsubsection{1.6.3\hspace{0.2cm}为什么不用constexpr?}

C++11后，可以使用constexpr提供在编译时计算某些值的能力。对于很多模板来说，这很有意义。

例如，为了能够在编译时使用maximum函数，必须声明它:

\hspace*{\fill} \\ %插入空行
\noindent
\textit{basics/maxconstexpr.hpp}
\begin{lstlisting}[style=styleCXX]
template<typename T1, typename T2>
constexpr auto max (T1 a, T2 b)
{
	return b < a ? a : b;
}
\end{lstlisting}

这样，就可以在有编译时使用maximum函数模板，比如在声明原始数组的大小时:

\begin{lstlisting}[style=styleCXX]
int a[::max(sizeof(char),1000u)];
\end{lstlisting}

或者定义\texttt{std::array<>}的大小:

\begin{lstlisting}[style=styleCXX]
std::array<std::string, ::max(sizeof(char),1000u)> arr;
\end{lstlisting}

注意，将1000作为unsigned int传递是为了避免在模板中比较有符号值和无符号值时，编译器发出的警告。

第8.2节将讨论使用constexpr的例子。为了让我们的注意力集中在基本特性上，在讨论其他模板特性时，我们通常会跳过constexpr。











